package com.dayuanit.dy16.atm.boatm.service.impl;

import com.dayuanit.dy16.atm.boatm.dto.MenuDTO;
import com.dayuanit.dy16.atm.boatm.entity.BoRole;
import com.dayuanit.dy16.atm.boatm.entity.BoUser;
import com.dayuanit.dy16.atm.boatm.entity.Permission;
import com.dayuanit.dy16.atm.boatm.exception.BizException;
import com.dayuanit.dy16.atm.boatm.mapper.BoRoleMapper;
import com.dayuanit.dy16.atm.boatm.mapper.BoUserMapper;
import com.dayuanit.dy16.atm.boatm.mapper.PermissionMapper;
import com.dayuanit.dy16.atm.boatm.service.IBoUserService;
import com.dayuanit.dy16.atm.boatm.vo.PerimissionRequestVO;
import com.dayuanit.dy16.atm.boatm.vo.UserRoleAllocationRequstVO;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BoUserServiceImpl implements IBoUserService {

    @Autowired
    private BoUserMapper boUserMapper;

    @Autowired
    private BoRoleMapper boRoleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Value("${atm.user.pwd.salt}")
    private String pwsSalt;

    @Override
    public void signUp(String username, String pwd) {
        if (StringUtils.isBlank(username) || StringUtils.isBlank(pwd)) {
            throw new BizException("有必填参数为空");
        }

        BoUser boUser = boUserMapper.getByName(username);
        if (null != boUser) {
            throw new BizException("用户已经存在");
        }

        String pwdSign = DigestUtils.md5Hex(pwd + username + pwsSalt);

        boUser = new BoUser();
        boUser.setCreateTime(new Date());
        boUser.setPassword(pwdSign);
        boUser.setUsername(username);
        boUserMapper.insert(boUser);
    }

    @Override
    public void createRole(String roleName, String roleValue) {
        if (StringUtils.isBlank(roleName) || StringUtils.isBlank(roleValue)) {
            throw new BizException("有必填参数为空");
        }

        BoRole boRole = boRoleMapper.getByName(roleName);
        if (null != boRole) {
            throw new BizException("角色已存在");
        }

        boRole = new BoRole();
        boRole.setRoleName(roleName);
        boRole.setRoleValue(roleValue);
        boRoleMapper.insert(boRole);
    }

    @Transactional
    @Override
    public void userRole(UserRoleAllocationRequstVO userRoleAllocationRequstVO) {
        if (userRoleAllocationRequstVO.getUsername() == null) {
            throw new BizException("请选择用户和角色");
        }

        if (userRoleAllocationRequstVO.getRoleIds() == null) {
            userRoleAllocationRequstVO.setRoleIds(Collections.EMPTY_LIST);
        }

        BoUser boUser = boUserMapper.getByName(userRoleAllocationRequstVO.getUsername());
        if (null == boUser) {
            throw new BizException("用户不存在");
        }

        //先删除所有的用户角色
        boRoleMapper.delUserRoles(boUser.getId());

        for (Long roleId : userRoleAllocationRequstVO.getRoleIds()) {
            boRoleMapper.saveUserRole(boUser.getId(), roleId);
        }
    }


    @Override
    public void delUserRole(Long userId, Long roleId) {
        boRoleMapper.delUserRole(userId, roleId);
    }

    @Override
    public List<BoRole> loadRole() {
        return boRoleMapper.listRoles();
    }

    @Override
    public List<Long> loadUserRoles(String username) {
        List<BoRole> boRoles = boRoleMapper.listUserRoles(username);

        //方案一：
//        List<Long> roleIds = new ArrayList<>();
//        for (BoRole role : boRoles) {
//            roleIds.add(role.getId());
//        }

        //方案二：
//        List<Long> roleIds = boRoles.stream().map(role -> role.getId())
//                .collect(Collectors.toList());

        //方案三：
        List<Long> roleIds = boRoles.stream().map(BoRole::getId)
                .collect(Collectors.toList());

        return roleIds;
    }

    @Override
    public void createPerimission(PerimissionRequestVO perimissionRequestVO) {
        if (StringUtils.isBlank(perimissionRequestVO.getPerimissionName())
                || StringUtils.isBlank(perimissionRequestVO.getPerimissionValue())) {
            throw new BizException("有必填参数为空");
        }

        Permission permission = new Permission();

        permission.setLeaf(perimissionRequestVO.getLeaf());
        permission.setMenu(perimissionRequestVO.getMenu());
        permission.setParentId(perimissionRequestVO.getParentId());
        permission.setPermissionName(perimissionRequestVO.getPerimissionName());
        permission.setPermissionValue(perimissionRequestVO.getPerimissionValue());
        permission.setUrl(perimissionRequestVO.getUrl());
        permissionMapper.insert(permission);
    }

    @Override
    public List<Permission> listFirstPermission() {
        return permissionMapper.listPermission(0L, 0, 1);
    }

    @Override
    public List<MenuDTO> loadMenu() {
        //所有的菜单
        List<Permission> permissions = permissionMapper.listPermission(null, null, 1);

        //方案一：
//        List<Permission> firstMenus = new ArrayList<>();
//        for (Permission permission : permissions) {
//            if (permission.getParentId() == 0) {
//                firstMenus.add(permission);
//            }
//        }

        //方案二：
        List<Permission> firstMenus = permissions.stream()
                .filter(el -> el.getParentId() == 0)
                .collect(Collectors.toList());

        Map<Long, List<Permission>> menuGroup = permissions.stream().collect(Collectors.groupingBy(el -> el.getParentId()));


        List<MenuDTO> dtos = new ArrayList<>();

        for (Permission first : firstMenus) {
            MenuDTO firstMenu = new MenuDTO();
            dtos.add(firstMenu);

            firstMenu.setMenuId(first.getId());
            firstMenu.setMenuValue(first.getPermissionValue());
            firstMenu.setParentId(first.getParentId());


            List<Permission> childs = menuGroup.get(first.getId());
            if (childs == null) {
                childs =  Collections.EMPTY_LIST;
            }
            List<MenuDTO> secondMenus = new ArrayList<>(childs.size());
            for (Permission second : childs) {
                MenuDTO secondMenu = new MenuDTO();
                secondMenu.setMenuValue(second.getPermissionValue());
                secondMenu.setMenuId(second.getId());
                secondMenu.setChilds(Collections.EMPTY_LIST);
                secondMenu.setParentId(second.getParentId());
                secondMenus.add(secondMenu);
            }

            firstMenu.setChilds(secondMenus);
        }

        return dtos;
    }

    @Override
    public List<MenuDTO> loadUnMenu() {

        List<Permission> permissions = permissionMapper.listPermission(null, null, 0);
        List<MenuDTO> dtos = new ArrayList<>(permissions.size());

        for (Permission permission : permissions) {
            MenuDTO menuDTO = new MenuDTO();
            menuDTO.setMenuId(permission.getId());
            menuDTO.setMenuValue(permission.getPermissionValue());

            dtos.add(menuDTO);
        }
        return dtos;
    }

    @Transactional
    @Override
    public void rolePerimissionAllocation(Long roleId, List<Long> menuIds, List<Long> unMenuIds) {
        if (null == roleId) {
            throw new BizException("请选择角色");
        }

        menuIds = menuIds == null ? Collections.EMPTY_LIST : menuIds;
        unMenuIds = unMenuIds == null ? Collections.EMPTY_LIST : unMenuIds;

        permissionMapper.delRolePermission(roleId);

        //方案一：
//        HashSet<Long> menuSet = new HashSet<>(menuIds.size());
//        for (Long menuId : menuIds) {
//            menuSet.add(menuId);
//        }

        //方案二：
        menuIds = menuIds.stream().distinct().collect(Collectors.toList());

        menuIds.addAll(unMenuIds);

        //方案一：单个添加 速度慢 大部分的时间浪费在通信上
//        for (Long menuId : menuIds) {
//            permissionMapper.insertRolePermission(roleId, menuId);
//        }

        //方案二：批量插入， 速度快 一次通信搞定
        permissionMapper.batchRolePermission(roleId, menuIds);
    }

    @Override
    public List<Permission> queryUserPermission(Long roleId) {
        List<Permission> permissions = permissionMapper.listByRoleId(roleId);
        permissions = permissions.stream().filter(el -> el.getLeaf() == 1 || el.getMenu() == 0).collect(Collectors.toList());
        return permissions;
    }

    @Override
    public List<MenuDTO> loadUserMenu(long userId) {
        List<Permission> permissions = permissionMapper.listMenuByUserId(userId);
        List<MenuDTO> dtos = new ArrayList<>();

        List<Permission> firstMenus = permissions.stream()
                .filter(el -> el.getParentId() == 0)
                .collect(Collectors.toList());

        Map<Long, List<Permission>> menuMap = permissions.stream().collect(Collectors.groupingBy(el -> el.getParentId()));

        for (Permission permission : firstMenus) {
            MenuDTO firstMenuDTO = new MenuDTO();
            firstMenuDTO.setMenuValue(permission.getPermissionValue());
            firstMenuDTO.setMenuId(permission.getId());
            firstMenuDTO.setParentId(permission.getParentId());

            List<Permission> childPermission = menuMap.get(permission.getId());
            List<MenuDTO> secondMenuDTOs = new ArrayList<>(childPermission.size());
            for (Permission second : childPermission) {
                MenuDTO secondMenuDto = new MenuDTO();
                secondMenuDto.setChilds(Collections.EMPTY_LIST);
                secondMenuDto.setParentId(second.getParentId());
                secondMenuDto.setMenuId(second.getId());
                secondMenuDto.setMenuValue(second.getPermissionValue());
                secondMenuDto.setUrl(second.getUrl());
                secondMenuDTOs.add(secondMenuDto);
            }

            firstMenuDTO.setChilds(secondMenuDTOs);
            dtos.add(firstMenuDTO);
        }
        return dtos;
    }

    @Override
    public BoUser login(String username, String password) {
        BoUser boUser = boUserMapper.getByName(username);
        if (null == boUser) {
            throw new BizException("用户名不存在或者密码错误");
        }

        String pwdSign = DigestUtils.md5Hex(password + username + pwsSalt);
        if (!boUser.getPassword().equals(pwdSign)) {
            throw new BizException("用户名不存在或者密码错误");
        }

        return boUser;
    }

    @Override
    public BoUser getUser(String username) {
        return boUserMapper.getByName(username);
    }

    /**
     * 根据用户名 查询当前用户对应的所有角色名称
     * @param username
     * @return
     */
    @Override
    public List<String> getUsersRoleName(String username) {
        List<BoRole> boRoles = boRoleMapper.listUserRoles(username);
        return boRoles.stream().map(el -> el.getRoleName()).collect(Collectors.toList());
    }
}
